/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.formserver.vmmanager.validate;

import com.inspur.edp.bef.bizentity.GspBizEntityElement;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.operation.BizMgrAction;
import com.inspur.edp.bef.bizentity.operation.collection.BizMgrActionCollection;
import com.inspur.edp.bef.component.ICompParameter;
import com.inspur.edp.bef.component.ICompParameterCollection;
import com.inspur.edp.bef.component.base.ReturnValue;
import com.inspur.edp.bef.component.detailcmpentity.vm.VMComponent;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.cef.designtime.api.collection.CommonDtmCollection;
import com.inspur.edp.cef.designtime.api.element.ElementDefaultVauleType;
import com.inspur.edp.cef.designtime.api.element.GspElementDataType;
import com.inspur.edp.cef.designtime.api.element.GspElementObjectType;
import com.inspur.edp.cef.designtime.api.element.GspEnumValue;
import com.inspur.edp.cef.designtime.api.operation.CommonOperation;
import com.inspur.edp.cef.designtime.api.variable.CommonVariableCollection;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import com.inspur.edp.das.commonmodel.entity.GspCommonModel;
import com.inspur.edp.das.commonmodel.entity.object.GspCommonObjectType;
import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.GspViewModelElement;
import com.inspur.edp.formserver.viewmodel.GspViewObject;
import com.inspur.edp.formserver.viewmodel.action.IViewModelParameter;
import com.inspur.edp.formserver.viewmodel.action.MappedCdpAction;
import com.inspur.edp.formserver.viewmodel.action.MappedCdpActionBase;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import com.inspur.edp.formserver.viewmodel.action.ViewModelActionType;
import com.inspur.edp.formserver.viewmodel.action.viewmodelbase.ViewModelReturnValue;
import com.inspur.edp.formserver.viewmodel.collection.VMActionCollection;
import com.inspur.edp.formserver.viewmodel.collection.ValueHelpConfigCollection;
import com.inspur.edp.formserver.viewmodel.common.VMParameterType;
import com.inspur.edp.formserver.viewmodel.common.ValueHelpConfig;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoElementSourceType;
import com.inspur.edp.formserver.viewmodel.common.mapping.GspVoObjectSourceType;
import com.inspur.edp.formserver.viewmodel.exception.ViewModelException;
import com.inspur.edp.formserver.viewmodel.i18n.VMI8nResourceUtil;
import com.inspur.edp.formserver.viewmodel.i18n.names.VoResourceKeyNames;
import com.inspur.edp.formserver.vmmanager.exception.VoManagerErrorCodes;
import com.inspur.edp.formserver.vmmanager.service.VmManagerService;
import com.inspur.edp.formserver.vmmanager.util.CheckInfoUtil;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.uri.MetadataURI;
import com.inspur.edp.lcm.metadata.api.service.RefCommonService;
import io.iec.edp.caf.commons.exception.ExceptionLevel;
import io.iec.edp.caf.commons.utils.CollectionUtils;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class ViewModelValidator {

    private final static String ERROR_CODE = "ViewModelValidate";
    private GspViewModel vm;
    private String metaPath;
    private GspBusinessEntity be;

    private void throwValidateException(String message) {
        throw new ViewModelException("", ERROR_CODE, message, null, ExceptionLevel.Error, false);
    }

    public final boolean validate(String path, GspViewModel vm) {
        this.vm = vm;
        this.metaPath = path;
        if (!vm.getIsVirtual()
                && vm.getMainObject().getMapping().getSourceType() == GspVoObjectSourceType.BeObject) {
            MetadataURI sourceURI = new MetadataURI(vm.getID());
            MetadataURI targetURI = new MetadataURI(vm.getMapping().getTargetMetadataId());
            GspMetadata dto = SpringBeanUtils.getBean(RefCommonService.class).getRefMetadata(targetURI, sourceURI, this.metaPath);
            if (dto == null || dto.getContent() == null) {
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0105,null, vm.getMapping().getTargetMetadataId());
            }
            be = (GspBusinessEntity) ((dto.getContent() instanceof GspBusinessEntity) ? dto.getContent() : null);
        }
        return validateModel()
                && validateObject()
                && validateElement()
                && validateVmActions()
                && validateDataExtendInfo()
                && validateHelpActions();
    }


    ///#region 模型
    private boolean validateModel() {
        boolean validateRez = true;
        //检查父子关联字段

        String valRes = validateModelBasicInfo(vm);
        if (!StringUtils.isEmpty(valRes)) {
            throwValidateException(valRes);
        }
        ArrayList<IGspCommonObject> objList = vm.getAllObjectList();
        StringBuilder sb = new StringBuilder();

        for (IGspCommonObject item : objList) {
            if (item.getObjectType() == GspCommonObjectType.MainObject) //不检查主对象
            {
                continue;
            }
            if (item.getKeys().size() == 0
                    || CheckInfoUtil.checkNull(item.getKeys().get(0).getSourceElement())
                    || CheckInfoUtil.checkNull(item.getKeys().get(0).getTargetElement())) {
                sb.append(item.getName()).append(",");
            }
        }
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0106, null, sb.toString());
        }

        // 变量实体
        String message = validateVarableEntity(vm);
        if (message.length() > 0) {
            throwValidateException(message);
            validateRez = false;
        }

        // 帮助前事件
        message = validateValueHelpConfigs(vm);
        if (message.length() > 0) {
            throwValidateException(message);
            validateRez = false;
        }
        return validateRez;
    }

    private String validateModelBasicInfo(GspViewModel model) {
        StringBuilder sb = new StringBuilder();
        if (CheckInfoUtil.checkNull(model.getCode())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_BASICINFO_CODE_ISNULL, model.getName()));
        } else {
            // 模型Code限制非法字符
            if (!ConformToNaminGspecification(model.getCode())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_BASICINFO_CODE_FORMATE, model.getName()));
                sb.append("\n");
            }
        }
        if (CheckInfoUtil.checkNull(model.getName())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_BASICINFO_NAME_ISNULL,model.getCode()));
        }
        return sb.toString();
    }

    /**
     * 是否符合命名规范
     * 字母数字下划线组成,字母下划线开头
     *
     * @param text 待检查文本
     * @return 是否符合规范
     */
    private boolean ConformToNaminGspecification(String text) {
        String regex = "^[A-Za-z_][A-Za-z_0-9]*$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(text);
        return matcher.matches();
    }

    private String validateVarableEntity(GspCommonModel model) {
        //validateObjectBasicInfo(model.Variables,sb,model.Name);
        return validateVariables(model);
    }

    private String validateVariables(GspCommonModel model) {
        CommonVariableCollection vars = model.getVariables().getContainElements();
        StringBuilder sb = new StringBuilder();
        if (vars != null && vars.size() > 0) {
            for (IGspCommonField variable : vars) {
                String errMsgPrefix = VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_VARIABLE_PREFIX,
                        model.getVariables().getName(), variable.getName());
                // 检查元素的基本信息
                validateElementBasicInfo(variable, sb, errMsgPrefix);
            }

            // 编号不可重复
            for (int i = 0; i < vars.size() - 1; i++) {
                IGspCommonField firstElement = vars.getItem(i);
                for (int j = i + 1; j < vars.size(); j++) {
                    IGspCommonField secondElement = vars.getItem(j);
                    if (firstElement.getCode().equals(secondElement.getCode())
                            && firstElement.getBelongObject().getID().equals(secondElement.getBelongObject()
                            .getID())) {
                        return VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_VARIABLES_CODE_DUPLICATE,
                                model.getName(), firstElement.getName(), secondElement.getName());
                    }
                }
            }
        }

        //联动计算
        CommonDtmCollection dtms = new CommonDtmCollection();
        dtms.addAll(model.getVariables().getDtmAfterCreate());
        dtms.addAll(model.getVariables().getDtmAfterModify());
        dtms.addAll(model.getVariables().getDtmBeforeSave());
        sb.append(validateVarDtms(dtms));

        return sb.toString();
    }

    private String validateVarDtms(CommonDtmCollection collection) {
        //联动计算
        ArrayList<CommonOperation> dtms = (ArrayList<CommonOperation>) collection.stream()
                .map(item -> (CommonOperation) item)
                .collect(Collectors.toList());
//		CommonDetermination[] dtms = (CommonDetermination[]) collection.toArray();
        //①必填项
        StringBuilder sb = new StringBuilder();
        sb.append(validateCommonOperationBasicInfo(dtms));
        if (sb.length() > 0) {
            return sb.toString();
        }
        //②编号重复
        sb.append(validateCommonOperationCodeRepeat(dtms));
        return sb.toString();
    }

    ///#endregion

    ///#region 对象

    /**
     * 校验对象基本信息
     */
    private boolean validateObject() {
        boolean validateRez = true;
        StringBuilder sb = new StringBuilder();

        ArrayList<IGspCommonObject> aObjectList = vm.getAllObjectList();

        //编号名称不允许为空
        for (IGspCommonObject aObject : aObjectList) {
            if (CheckInfoUtil.checkNull(aObject.getCode())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OBJECT_CODEISNULL, aObject.getName()));
                sb.append("\n");
            } else {
                // 对象Code限制非法字符
                if (!conformToNaminGspecification(aObject.getCode())) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OBJECT_CODEFORMATION, aObject.getName()));
                    sb.append("\n");
                }
            }
            if (CheckInfoUtil.checkNull(aObject.getName())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OBJECT_NAMEISNULL, aObject.getCode()));
                sb.append("\n");
            }
        }

        //编号不允许重复
        for (int i = 0; i < aObjectList.size() - 1; i++) {
            IGspCommonObject firstObj = aObjectList.get(i);
            for (int j = i + 1; j < aObjectList.size(); j++) {
                IGspCommonObject secondObj = aObjectList.get(j);
                if (firstObj.getCode().compareToIgnoreCase(secondObj.getCode()) == 0) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OBJECT_CODE_DUPLICATE, firstObj.getName(), secondObj.getName()));
                    sb.append("\n");
                }
            }
        }

        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
            throwValidateException(sb.toString());
            validateRez = false;
        }

        return validateRez;
    }

    ///#endregion

    ///#region 字段

    /**
     * 检验所有字段[编号][名称][标签]不允许为空，同一对象上所有字段的[编号][名称][标签]不允许重复
     */
    private boolean validateElement() {
        boolean validateRez = true;
        StringBuilder sb = new StringBuilder();

        ArrayList<IGspCommonObject> aObjectList = vm.getAllObjectList();
        for (IGspCommonObject aObject : aObjectList) {
            ArrayList<IGspCommonElement> allElementList = aObject.getAllElementList(false);

            if (allElementList != null && allElementList.size() > 0) {
                //字段[编号][名称][标签]不允许为空
                for (IGspCommonElement element : allElementList) {
                    String errorMessagePrefix = VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_PREFIX,
                            aObject.getName(), element.getName());
                    validateElementBasicInfo(element, sb, errorMessagePrefix);
                }

                //同一对象上所有字段的[编号][名称][标签]不允许重复
                for (int i = 0; i < allElementList.size() - 1; i++) {
                    IGspCommonElement firstElement = allElementList.get(i);
                    for (int j = i + 1; j < allElementList.size(); j++) {
                        IGspCommonElement secondElement = allElementList.get(j);
                        if (firstElement.getCode().equals(secondElement.getCode()) && firstElement
                                .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
                            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_CODE_DUPLICATE,
                                    firstElement.getBelongObject().getName(), firstElement.getName(),
                                    secondElement.getName()));
                            sb.append("\n");
                        }
                        if (firstElement.getName().equals(secondElement.getName()) && firstElement
                                .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
                            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_NAME_DUPLICATE,
                                    firstElement.getBelongObject().getName(), firstElement.getName(),
                                    secondElement.getName()));
                            sb.append("\n");
                        }
                        if (firstElement.getLabelID().equals(secondElement.getLabelID()) && firstElement
                                .getBelongObject().getID().equals(secondElement.getBelongObject().getID())) {
                            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_LABEL_DUPLICATE,
                                    firstElement.getBelongObject().getName(), firstElement.getName(),
                                    secondElement.getName()));
                            sb.append("\n");
                        }
                    }
                }

                // 结合beObject检查
                checkWithBeObject((GspViewObject) ((aObject instanceof GspViewObject) ? aObject : null),
                        allElementList);

            }
        }
        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
            throwValidateException(sb.toString());
            validateRez = false;
        }
        return validateRez;
    }

    public String getFormat(String formatStr) {
        return null;
    }

    private void validateElementBasicInfo(IGspCommonField element, StringBuilder sb, String errorMessage) {
        if (CheckInfoUtil.checkNull(element.getCode())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_CODE_IS_NULL,errorMessage))
                    .append("\n");
        } else if (!conformToNaminGspecification(element.getCode())) {
            // 字段Code限制非法字符
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_CODE_FORMAT,errorMessage))
                    .append("\n");
        }
        if (CheckInfoUtil.checkNull(element.getName())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_NAME_IS_NULL,errorMessage))
                    .append("\n");
        }

        if (CheckInfoUtil.checkNull(element.getLabelID()) || CheckInfoUtil.checkNull(element.getLabelID().trim())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_LABEL_IS_NULL,errorMessage))
                    .append("\n");
        } else {
            // LabelID在表单和报表中用作XML的标签，要限制非法字符
            String re = "^[A-Za-z_][A-Za-z_\\d-.]*$";
            if (!getRegx(re, element.getLabelID().trim())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_LABEL_FORMAT,errorMessage))
                        .append("\n");
            }
        }

        if (element.getObjectType() == GspElementObjectType.Enum) {
            if (element.getContainEnumValues().size() == 0) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_ENUM_IS_EMPTY,errorMessage))
                        .append("\n");
            }

            // 枚举类型字段，校验默认值为枚举编号
            if (!CheckInfoUtil.checkNull(element.getDefaultValue())) {
                String defaultValue = element.getDefaultValue();
                boolean isEnumKey = false;
                for (GspEnumValue enumValue : element.getContainEnumValues()) {
                    if (defaultValue.equals(enumValue.getValue())) {
                        isEnumKey = true;
                        break;
                    }
                }
                if (!isEnumKey) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_DEFAULTVALUE_FIT_ENUM,errorMessage));
                }
            }
            // 枚举类型字段，非必填
            if (element.getIsRequire()) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_ENUM_REQUIRED_NOT_NO, errorMessage))
                        .append("\n");
            }
        }

        if (!element.getIsVirtual()) { //资金在be上创建了长度为0的虚拟字段(因不希望长度校验), vo上校验临时增加兼容
            if (element.getMDataType() == GspElementDataType.Decimal) {
                if (element.getLength() == 0) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_DECIMAL_LENGTH_IS_ZERO,
                            errorMessage))
                            .append("\n");
                }

                if (element.getPrecision() == 0) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_DECIMAL_PRECISION_IS_ZERO,
                            errorMessage)).append("\n");
                }
            }

            if (element.getMDataType() == GspElementDataType.String) {
                if (element.getLength() == 0) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_BASIC_STRING_LENGTH_IS_ZERO,
                            errorMessage)).append("\n");
                }
            }
        }
        // 默认值类型校验
        String message = validateElementDefaultValue(element, errorMessage);
        if (!StringUtils.isEmpty(message)) {
            sb.append(message);
            sb.append("\n");
        }
    }

    /**
     * 正则化判断证书小数
     */
    private boolean getRegx(String regex, String regexStr) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(regexStr);
        return matcher.matches();
    }

    private String validateElementDefaultValue(IGspCommonField ele, String errorMessage) {
        StringBuilder sb = new StringBuilder();
        String reInt = "^-?\\d+$"; //判断整数，负值也是整数
        String reDecimalString = String.format("^-?(([0-9]+\\.[0-9]{0,%1$s})|-?([0-9]*\\.[0-9]{0,%1$s})|-?([1-9][0-9]+)|([0-9]))$",
                        ele.getPrecision());

        // 20190523-整型枚举可设置枚举编号为默认值；关联/udt默认值暂不支持；
        if (ele.getObjectType() != GspElementObjectType.None) {
            return sb.toString();
        }

        GspElementDataType type = ele.getMDataType();
        String value = ele.getDefaultValue();
        if (ele.getDefaultValueType() == ElementDefaultVauleType.Expression) {
            return sb.toString();
        }
        boolean isValidate = true;
        if (!CheckInfoUtil.checkNull(value)) {
            switch (type) {
                case Integer:
                    if (!getRegx(reInt, value)) {
                        isValidate = false;
                    }
                    break;
                case Decimal:
                    if (!getRegx(reDecimalString, value)) {
                        sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_DEFAULT_DECIMAL_NOT_FIT,
                                        errorMessage)).append("\n");
                        return sb.toString();
                    }
                    break;
                case Date:
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        sdf.parse(value);
                    } catch (Exception e) {
                        isValidate = false;
                    }
                    break;
                case DateTime:
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        sdf.parse(value);
                    } catch (Exception e) {
                        isValidate = false;
                    }
                    break;
                case Boolean:
                    if (!value.equalsIgnoreCase("true") && !value.equalsIgnoreCase("false")) {
                        isValidate = false;
                    }
                    break;
                case Binary:
                    if (!StringUtils.isBlank(value)) {
                        isValidate = false;
                    }
                    break;
                case String:
                case Text:
                default:
                    break;
            }
        }
        if (!isValidate) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ELEMENT_DEFAULT_DATATYPE_NOT_FIT, errorMessage))
                    .append("\n");
        }
        return sb.toString();
    }

    /**
     * 结合bizObject检查
     */
    private void checkWithBeObject(GspViewObject aObject,
                                   ArrayList<IGspCommonElement> allElementList) {
        // 虚拟对象无映射bizObj
        if (aObject.getIsVirtual() || aObject.getMapping().getSourceType() != GspVoObjectSourceType.BeObject) {
            return;
        }

        // 其他be源暂不检查
        if (!aObject.getMapping().getTargetMetadataId().equals(be.getID())) {
            return;
        }

        IGspCommonObject beObject = be.getAllObjectList().stream()
                .filter(item -> item.getID().equals(aObject.getMapping().getTargetObjId()))
                .findFirst().orElse(null);
        //.FirstOrDefault(item => String.equals(item.ID, ((GspViewObject)aObject).getMapping().TargetObjId));
        if (beObject == null) {
            throw  new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0104, null,
                    aObject.getName(), aObject.getMapping().getTargetObjId());
        }
        ArrayList<IGspCommonElement> beElementList = beObject.getAllElementList(false);

        // vm字段长度不得大于映射的be字段长度
        for (IGspCommonElement element : allElementList) {

            GspViewModelElement vmEle = (GspViewModelElement) element;
            if (vmEle.getIsVirtualViewElement()
                    || vmEle.getMapping().getSourceType() != GspVoElementSourceType.BeElement
                    || !vmEle.getMapping().getTargetMetadataId().equals(be.getID())) {
                continue;
            }

            GspBizEntityElement beEle = (GspBizEntityElement) beElementList.stream()
                    .filter(item -> item.getID().equals(((GspViewModelElement) element).getMapping().getTargetObjId()))
                    .findFirst()
                    .orElse(null);
            if (beEle == null) {
                GspBizEntityElement beEle2 = (GspBizEntityElement) be.findElementById(((GspViewModelElement) element).getMapping().getTargetObjId());
                // 当前字段不是当前bizObj引入，不抛异常
                if (beEle2 != null) {
                    continue;
                }
                throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0107,null,
                        aObject.getName(), element.getName(),
                        ((GspViewModelElement) element).getMapping().getTargetObjectId());
            } else {
                if (element.getLength() > beEle.getLength()) {
                    throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0108,null,
                             aObject.getName(), element.getName() , String.valueOf(beEle.getLength()));
                }
                if (element.getPrecision() > beEle.getPrecision()) {
                    throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0109,null,
                             aObject.getName() , element.getName(), String.valueOf(beEle.getPrecision()));
                }
            }
        }
    }

    /**
     * [操作]视图对象操作
     */
    private boolean validateVmActions() {
        ArrayList<ViewModelAction> actions = vm.getActions();
        String errorMessage = VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_VM_ACTION_PREFIX);
        StringBuilder sb = new StringBuilder();
        boolean validateRez = validateActionsBasicInfo(actions, errorMessage, sb);

        if (!vm.getIsVirtual()
                && vm.getMainObject().getMapping().getSourceType() == GspVoObjectSourceType.BeObject) {

            BizMgrActionCollection mgrActions = be.getBizMgrActions();
            //④检查be带出操作是否已删除
            if (!actions.isEmpty()) {
                for (ViewModelAction vmAction : actions) {
                    if (vmAction.getType() == ViewModelActionType.BEAction) {
                        BizMgrAction mgrAction = (BizMgrAction) mgrActions.stream()
                                .filter(item -> item.getID().equals(vmAction.getMapping().getTargetObjId()))
                                .findFirst()
                                .orElse(null);//Find(item => item.ID == vmAction.Mapping.TargetObjId);
                        if (mgrAction == null) {
                            throw new ViewModelException(VoManagerErrorCodes.GSP_VIEWOBJECT_MANAGER_0110, null,
                                    vmAction.getName(), vmAction.getMapping().getTargetObjId());
                        }
                    } else {
                        String errorMsg = validComp(vmAction);
                        if (!StringUtils.isEmpty(errorMsg)) {
                            throwValidateException(errorMsg);
                        }
                    }
                }
            }
        }

        if (sb.length() > 0) {
            throwValidateException(sb.toString());
            validateRez = false;
        }
        return validateRez;
    }

    private String validComp(ViewModelAction vmAction) {
        StringBuilder sb = new StringBuilder();

        if (!(vmAction instanceof MappedCdpActionBase)) {
            return "";
        }
        MappedCdpActionBase mappedCdpActionBase = (MappedCdpActionBase) vmAction;
        if (mappedCdpActionBase.getIsGenerateComponent() || StringUtils.isEmpty(mappedCdpActionBase.getComponentEntityId())) {
            return "";
        }
        //如果是引用已有构件,需要做参数校验
        RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);
        GspMetadata metadata = metadataService.getRefMetadata(((MappedCdpActionBase) vmAction).getComponentEntityId());
        if (metadata == null) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMPONENT_METADATA_NOT_EXIST, vmAction.getName()));
            sb.append("\n");
            return sb.toString();
        }
        ICompParameterCollection compParameterCollection;
        if (metadata.getContent() instanceof VMComponent) {
            VMComponent component = (VMComponent) metadata.getContent();
            compParameterCollection = component.getMethod().getCompParameterCollection();
            int oprParSize = vmAction.getParameterCollection() == null ? 0 : vmAction.getParameterCollection().getCount();
            int compParSize = compParameterCollection == null ? 0 : compParameterCollection.getCount();
            if (oprParSize != compParSize) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMPONENT_PARAMETER_NUMBER_NOT_EQUAL,
                        vmAction.getName(), component.getName(), oprParSize, compParSize));
                sb.append("\n");
                return sb.toString();
            }
            if (!mappedCdpActionBase.getIsGenerateComponent()) {
                for (int i = 0; i < vmAction.getParameterCollection().getCount(); i++) {
                    IViewModelParameter viewModelParameter = vmAction.getParameterCollection().getItem(i);
                    ICompParameter compParameter = compParameterCollection.getItem(i);
                    //引用构件的才校验
                    sb.append(validVMCompParameter(viewModelParameter, compParameter, vmAction, component.getName()));
                }
                sb.append(validReturnValue(vmAction, component));
            }
        }
        return sb.toString();
    }

    private String validReturnValue(ViewModelAction vmAction, VMComponent vmComponent) {
        StringBuilder sb = new StringBuilder();
        ViewModelReturnValue vmReturnValue = vmAction.getReturnValue();
        ReturnValue returnValue = vmComponent.getVmMethod().getReturnValue();
        //返回值为空 不校验
        if ("void".equalsIgnoreCase(vmReturnValue.getDotnetClassName()) && "void".equalsIgnoreCase(returnValue.getDotnetClassName()))
            return "";

        if (!StringUtils.equalsIgnoreCase(vmReturnValue.getClassName(), returnValue.getClassName())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_RETURNVALUE_TYPE_NOT_EQUAL,
                    vmAction.getName(), vmComponent.getName()));
        }
        if (vmReturnValue.getCollectionParameterType().getValue() != returnValue.getParameterCollectionType().getValue()) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_RETURNVALUE_COLLECTION_TYPE_NOT_EQUAL,
                    vmAction.getName(), vmComponent.getName()));
        }
        return sb.toString();
    }

    private String validVMCompParameter(IViewModelParameter viewModelParameter, ICompParameter compParameter, ViewModelAction vmActionBase, String componentName) {
        StringBuilder sb = new StringBuilder();
        if (!StringUtils.equalsIgnoreCase(viewModelParameter.getParamCode(), compParameter.getParamCode())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMPONENT_PARAMETER_CODE_NOT_EQUAL,
                    vmActionBase.getName(), viewModelParameter.getParamCode(),
                    componentName, compParameter.getParamCode()));
        }
        if (!StringUtils.equalsIgnoreCase(viewModelParameter.getClassName(), compParameter.getClassName())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMPONENT_PARAMETER_TYPE_NOT_EQUAL,
                    vmActionBase.getName(), viewModelParameter.getParamCode(),
                    componentName, viewModelParameter.getClassName(), compParameter.getClassName()));
        }
        return sb.toString();
    }

    private boolean validateActionsBasicInfo(ArrayList<ViewModelAction> actions,
                                             String errorMessage, StringBuilder sb) {
        boolean validateRez = true;

        //①必填项
        sb.append(validateOperationBasicInfo(errorMessage, actions));
        if (sb.length() > 0) {
            throwValidateException(sb.toString());
            validateRez = false;
        }
        //②编号重复
        sb.append(validateOperationCodeRepeat(errorMessage, actions));
        if (sb.length() > 0) {
            throwValidateException(sb.toString());
            validateRez = false;
        }
        //③参数及返回值校验
        sb.append(validateActionParas(errorMessage, actions));
        if (sb.length() > 0) {
            throwValidateException(sb.toString());
            validateRez = false;
        }
        return validateRez;
    }

    private boolean validateHelpActions() {
        boolean validateRez = true;
        StringBuilder sb = new StringBuilder();
        ArrayList<ViewModelAction> actions = new ArrayList<>();

        ArrayList<IGspCommonElement> elementList = vm.getAllElementList(true);

        for (IGspCommonElement item : elementList) {
            GspViewModelElement element = (GspViewModelElement) item;
            if (element.getHelpActions() != null) {
                actions.addAll(element.getHelpActions());
            }

        }
        String errorMessage = VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_VM_ACTION_PREFIX);
        //①必填项
        sb.append(validateOperationBasicInfo(errorMessage, actions));
        if (sb.length() > 0) {
            throwValidateException(sb.toString());
            validateRez = false;
        }
        //②编号重复
        sb.append(validateOperationCodeRepeat(errorMessage, actions));
        if (sb.length() > 0) {
            throwValidateException(sb.toString());
            validateRez = false;
        }

        return validateRez;
    }

    /**
     * [操作]编号重复
     */
    private String validateOperationCodeRepeat(String errorMessage, ArrayList<ViewModelAction> operations) {
        String sb = "";
        if (CollectionUtils.isEmpty(operations)) {
            return sb;
        }
        Map<String, String> keys = new HashMap<>();
        for (ViewModelAction operation : operations) {
            String originName = keys.put(operation.getCode(), operation.getName());
            if (originName != null) {
                return VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OPERATION_CODE_DUPLICATE,
                        errorMessage, operation.getName(), originName, operation.getCode());
            }
        }
        return sb;
    }

    /**
     * [操作]编号名称为空
     */
    private String validateOperationBasicInfo(String errorMessage, ArrayList<ViewModelAction> oprs) {
        if (oprs == null || oprs.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();

        for (ViewModelAction opr : oprs) {
            if (CheckInfoUtil.checkNull(opr.getCode())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OPERATION_BASIC_CODE_IS_NULL,
                                errorMessage, opr.getName())).append("\n");
            } else {
                // 操作Code限制非法字符
                if (!conformToNaminGspecification(opr.getCode())) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OPERATION_BASIC_CODE_FORMATE,
                            errorMessage, opr.getName())).append("\n");
                }
            }
            if (CheckInfoUtil.checkNull(opr.getName())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_OPERATION_BASIC_NAME_IS_NULL,
                        errorMessage, opr.getCode())).append("\n");
            }
        }
        return sb.toString();
    }

    /**
     * [操作]编号重复
     */
    private String validateCommonOperationCodeRepeat(ArrayList<CommonOperation> operations) {
        String sb = "";
        if (CollectionUtils.isEmpty(operations)) {
            return sb;
        }
        Map<String, String> keys = new HashMap<>();
        for (CommonOperation operation : operations) {
            String originName = keys.put(operation.getCode(), operation.getName());
            if (originName != null) {
                return VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMMON_OP_CODE_DUPLICATE,
                        operation.getCode(), originName, operation.getName());
            }
        }
        return sb;
    }

    /**
     * [操作]编号名称为空
     */
    private String validateCommonOperationBasicInfo(ArrayList<CommonOperation> oprs) {
        if (CollectionUtils.isEmpty(oprs)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();

        for (CommonOperation opr : oprs) {
            if (CheckInfoUtil.checkNull(opr.getCode())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMMON_OP_BASIC_CODE_IS_NULL,
                        opr.getName())).append("\n");
            } else {
                // 操作Code限制非法字符
                if (!conformToNaminGspecification(opr.getCode())) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMMON_OP_BASIC_CODE_FORMATE,
                            opr.getName())).append("\n");
                }
            }
            if (CheckInfoUtil.checkNull(opr.getName())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMMON_OP_BASIC_NAME_IS_NULL,
                        opr.getCode())).append("\n");
            }
        }
        return sb.toString();
    }

    /**
     * [操作]-action-参数
     */
    private String validateActionReturnValue(ViewModelAction opr, String errorMessage) {
        StringBuilder sb = new StringBuilder();
        ViewModelReturnValue returnValue = opr.getReturnValue();
        if (returnValue == null || returnValue.getParameterType() != VMParameterType.Custom) {
            return sb.toString();
        }
        if (!VmManagerService.creatJavaModule(metaPath)) {
            return sb.toString();
        }
        if (opr instanceof MappedCdpActionBase && !((MappedCdpActionBase) opr).getIsGenerateComponent()) {
            return sb.toString();
        }
        if (CheckInfoUtil.checkNull(returnValue.getClassName())) {
            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_RETURNVALUE_CLASS_ISNULL,
                    errorMessage, opr.getName()));
            sb.append("\n");
        }
        return sb.toString();
    }


    /**
     * 校验动作参数及返回值
     */
    private String validateActionParas(String errorMessage,
                                       ArrayList<ViewModelAction> actions) {
        StringBuilder sb = new StringBuilder();
        if (!CollectionUtils.isEmpty(actions)) {
            for (ViewModelAction action : actions) {
                sb.append(validateActionParas(action, errorMessage));
                sb.append(validateActionReturnValue(action, errorMessage));
                sb.append(validateActionComponent(action));
            }
        }
        return sb.toString();
    }


    private String validateActionComponent(ViewModelAction action) {
        StringBuilder sb = new StringBuilder();
        if (action instanceof MappedCdpAction) {
            MappedCdpAction mappedCdpAction = (MappedCdpAction) action;
            if (mappedCdpAction.getIsGenerateComponent() || StringUtils.isEmpty(mappedCdpAction.getComponentEntityId()))
                return "";
            RefCommonService metadataService = SpringBeanUtils.getBean(RefCommonService.class);
            GspMetadata metadata = metadataService.getRefMetadata(((MappedCdpActionBase) action).getComponentEntityId());
            if (metadata == null) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_COMPONENT_METADATA_NOT_EXIST,
                        action.getName())).append("\n");
                return sb.toString();
            }
        }
        return sb.toString();
    }

    private String validateActionParas(ViewModelAction opr, String message) {
        StringBuilder sb = new StringBuilder();
        //参数编号名称不可为空

        for (Object para : opr.getParameterCollection()) {
            if (CheckInfoUtil.checkNull(((IViewModelParameter) para).getParamCode())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_PARAM_CODE_IS_NULL,
                        message, opr.getName(), ((IViewModelParameter) para).getParamName())).append("\n");
            } else {
                // 参数编号Code限制非法字符
                if (!conformToNaminGspecification(((IViewModelParameter) para).getParamCode())) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_PARAM_CODE_FORMATE,
                            message, opr.getName(), ((IViewModelParameter) para).getParamName())).append("\n");
                }
            }
            if (CheckInfoUtil.checkNull(((IViewModelParameter) para).getParamName())) {
                sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_PARAM_NAME_IS_NULL,
                        message, opr.getName(), ((IViewModelParameter) para).getParamCode())).append("\n");
            }
            if (((IViewModelParameter) para).getParameterType() == VMParameterType.Custom) {
                if (VmManagerService.creatJavaModule(metaPath)) {
                    if (!(opr instanceof MappedCdpActionBase) || ((MappedCdpActionBase) opr).getIsGenerateComponent()) {
                        if (CheckInfoUtil.checkNull(((IViewModelParameter) para).getClassName())) {
                            sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_PARAM_CLASS_IS_NULL,
                                    message ,opr.getName(), ((IViewModelParameter) para).getParamName()))
                                    .append("\n");
                        }
                    }
                }
            }
        }
        if (sb.length() > 0) {
            return sb.toString();
        }

        //参数编号不可重复
        if (opr.getParameterCollection() != null && opr.getParameterCollection().getCount() > 0) {
            Map<String, String> codeSet = new HashMap<>();
            for (int i = 0; i < opr.getParameterCollection().getCount() - 1; i++) {
                IViewModelParameter para = opr.getParameterCollection().getItem(i);
                String originName = codeSet.put(para.getParamCode(), para.getParamName());
                if (originName != null) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_ACTION_PARAM_CODE_DUPLICATE,
                            message, opr.getName(),para.getParamCode(), originName, para.getParamName()));
                    sb.append("\n");
                }
            }
        }
        return sb.toString();
    }

    ///#endregion

    ///#region 扩展操作

    /**
     * 校验扩展操作
     */
    private boolean validateDataExtendInfo() {
        StringBuilder sb = new StringBuilder();
        return validateExtendActionsBasicInfo(vm.getDataExtendInfo().getDataMappingActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_DATAMAPPING_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeQueryActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_BEFOREQUERY_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getQueryActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_QUERY_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterQueryActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_AFTERQUERY_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeRetrieveActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_BEFORERETRIEVE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getRetrieveActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_RETRIEVE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterRetrieveActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_AFTERRETRIEVE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeModifyActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_BEFOREMODIFY_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getModifyActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_MODIFY_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterModifyActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_AFTERMODIFY_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getChangesetMappingActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_CHANGESETMAPPING_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeCreateActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_BEFORECREATE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getCreateActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_CREATE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterCreateActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_AFTERCREATE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeDeleteActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_BEFOREDELETE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getDeleteActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_DELETE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterDeleteActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_AFTERDELETE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeSaveActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_BEFORESAVE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getDataReversalMappingActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_DATAREVERSALMAPPING_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterSaveActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_AFTERSAVE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getChangesetReversalMappingActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_CHANGESETREVERSALMAPPING_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getBeforeMultiDeleteActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_BEFOREMULTIDELETE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getMultiDeleteActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_MULTIDELETE_ACTION))
            && validateExtendActionsBasicInfo(vm.getDataExtendInfo().getAfterMultiDeleteActions(),sb ,
                VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_DATAEXTEND_PREFIX_AFTERMULTIDELETE_ACTION));
    }

    private boolean validateExtendActionsBasicInfo(ArrayList<ViewModelAction> actions, StringBuilder sb, String errorMessage) {
        if (actions.isEmpty()) {
            return true;
        }
        return validateActionsBasicInfo(actions, errorMessage, sb);
    }

    ///#endregion

    ///#region 帮助前事件

    private String validateValueHelpConfigs(GspViewModel model) {
        StringBuilder sb = new StringBuilder();
        ValueHelpConfigCollection configs = model.getValueHelpConfigs();
        if (!CollectionUtils.isEmpty(configs)) {
            Set<String> keys = new HashSet<>();
            for (ValueHelpConfig config : configs) {
                if (!keys.add(config.getElementId())) {
                    return VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_HELP_CONFIG_PREFIX_ELEMENT_DUPLICATE,
                            config.getElementId());
                }

                if (CheckInfoUtil.checkNull(config.getElementId())) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_HELP_CONFIG_PREFIX_ELEMENTID_IS_NULL,
                            config.getHelperId()));
                    sb.append("\n");
                }
                if (CheckInfoUtil.checkNull(config.getHelperId())) {
                    sb.append(VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_HELP_CONFIG_PREFIX_ELEMENTID_IS_NULL,
                            config.getElementId()));
                    sb.append("\n");
                }

                if (config.getHelpExtend() != null && !CollectionUtils.isEmpty(config.getHelpExtend().getBeforeHelp())) {
                    VMActionCollection actions = config.getHelpExtend().getBeforeHelp();
                    String errorMessage = VMI8nResourceUtil.getMessage(VoResourceKeyNames.VALIDATE_HELP_ACTION_PREFIX,
                            config.getElementId());
                    validateActionsBasicInfo(actions, errorMessage, sb);
                }
            }
        }
        sb.append(validateVariables(model));
        return sb.toString();
    }
    /**
     * 是否符合命名规范 字母数字下划线组成,字母下划线开头
     */
    private boolean conformToNaminGspecification(String text) {
        String re = "^[A-Za-z_][A-Za-z_0-9]*$";

        Pattern pattern = Pattern.compile(re);
        Matcher matcher = pattern.matcher(text);
        return matcher.matches();
    }

    ///#endregion
}